{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Calculating Origin Destinations nXn Matrix given set of origins and destinations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "toc": true
   },
   "source": [
    "<h2>Table of Contents<span class=\"tocSkip\"></span></h2>\n",
    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Origin-Destinations-nXn-Matrix-given-set-of-origins-and-destinations\" data-toc-modified-id=\"Origin-Destinations-nXn-Matrix-given-set-of-origins-and-destinations-1\">Origin Destinations nXn Matrix given set of origins and destinations</a></span><ul class=\"toc-item\"><li><span><a href=\"#Create-origins-layer:\" data-toc-modified-id=\"Create-origins-layer:-1.1\">Create origins layer:</a></span></li><li><span><a href=\"#Get-destinations-layer:\" data-toc-modified-id=\"Get-destinations-layer:-1.2\">Get destinations layer:</a></span></li><li><span><a href=\"#Convert-to-matrix-format\" data-toc-modified-id=\"Convert-to-matrix-format-1.3\">Convert to matrix format</a></span></li><li><span><a href=\"#Conclusion\" data-toc-modified-id=\"Conclusion-1.4\">Conclusion</a></span></li></ul></li></ul></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "The [Origin Destination(OD) Cost Matrix service](http://desktop.arcgis.com/en/arcmap/latest/extensions/network-analyst/od-cost-matrix.htm) helps you to create an OD cost matrix for multiple `origins` to multiple `destinations`. An OD cost matrix is a table that contains cost, such as travel time or travel distance, from each origin to each destination. Additionally, it ranks the destinations in ascending order based on the minimum cost required to travel. When generating an OD cost matrix, you can optionally specify the maximum number of destinations to find for each origin and the maximum time or distance to travel when searching for destinations.\n",
    "\n",
    "By default, the matrix is generated with columns - origin id, destination id, destination rank, total time and total distance. \n",
    "In this sample notebook , we will use this tool to get OD matrix if given a set of origin and destination points, either as a csv with latitude and longitude or csv file with list of addresses. In later part of this sample, we will format the table to get n by n matrix.\n",
    "\n",
    "This is useful when you want to solve other transportation problems with open source tools or heuristics. When it comes to real world TSP(Travelling Salesman Problem) or VRP(Vehicle Routing Problem) or other tranportation problems, data about travel time from every point to every other point can give you more realistic results than with euclidean distance."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note** :If you run the tutorial using ArcGIS Online, 0.003 [credit](https://www.esri.com/en-us/arcgis/products/arcgis-online/pricing/credits) will be consumed as there are 6 origin-destination pairs.\n",
    "\n",
    "As a first step, let's import required libraries and establish a connection to your organization which could be an ArcGIS Online organization or an ArcGIS Enterprise. If you dont have an ArcGIS account, [get ArcGIS Trial](https://www.esri.com/en-us/arcgis/trial)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import arcgis\n",
    "from arcgis.gis import GIS\n",
    "import pandas as pd\n",
    "import datetime\n",
    "import getpass\n",
    "from IPython.display import HTML\n",
    "\n",
    "from arcgis import geocoding\n",
    "from arcgis.features import Feature, FeatureSet\n",
    "from arcgis.features import GeoAccessor, GeoSeriesAccessor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_gis = GIS(profile=\"your_online_profile\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will see how to create layer for origins and destinations when we have latitude and longitude and when we have addresses to geocode for converting to layer respectively."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create origins layer:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have latitude and longitude information for origins, with the following code snippet, we can create a layer from the information. We will reverse geocode the latitude longitude information to find the locations.\n",
    "\n",
    "**Note**: Geocoding the addresses will consume [credits](https://www.esri.com/en-us/arcgis/products/arcgis-online/pricing/credits)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<FeatureSet> 2 features"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "origin_coords = ['-117.187807, 33.939479', '-117.117401, 34.029346']\n",
    "origin_features = []\n",
    "\n",
    "for origin in origin_coords:\n",
    "    reverse_geocode = geocoding.reverse_geocode({\"x\": origin.split(',')[0], \n",
    "                                              \"y\": origin.split(',')[1]})    \n",
    "\n",
    "    origin_feature = Feature(geometry=reverse_geocode['location'], \n",
    "                           attributes=reverse_geocode['address'])\n",
    "    origin_features.append(origin_feature)\n",
    "\n",
    "origin_fset = FeatureSet(origin_features, geometry_type='esriGeometryPoint',\n",
    "                          spatial_reference={'latestWkid': 4326})\n",
    "origin_fset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get destinations layer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div class=\"item_container\" style=\"height: auto; overflow: hidden; border: 1px solid #cfcfcf; border-radius: 2px; background: #f6fafa; line-height: 1.21429em; padding: 10px;\">\n",
       "                    <div class=\"item_left\" style=\"width: 210px; float: left;\">\n",
       "                       <a href='https://geosaurus.maps.arcgis.com/home/item.html?id=63bfd57bac8240cba976b9e3f6745ca0' target='_blank'>\n",
       "                        <img src='' width='200' height='133' class=\"itemThumbnail\">\n",
       "                       </a>\n",
       "                    </div>\n",
       "\n",
       "                    <div class=\"item_right\"     style=\"float: none; width: auto; overflow: hidden;\">\n",
       "                        <a href='https://geosaurus.maps.arcgis.com/home/item.html?id=63bfd57bac8240cba976b9e3f6745ca0' target='_blank'><b>destinations_address</b>\n",
       "                        </a>\n",
       "                        <br/><br/><img src='https://geosaurus.maps.arcgis.com/home/js/jsapi/esri/css/images/item_type_icons/featureshosted16.png' style=\"vertical-align:middle;\" width=16 height=16>Feature Layer Collection by api_data_owner\n",
       "                        <br/>Last Modified: August 31, 2024\n",
       "                        <br/>0 comments, 19 views\n",
       "                    </div>\n",
       "                </div>\n",
       "                "
      ],
      "text/plain": [
       "<Item title:\"destinations_address\" type:Feature Layer Collection owner:api_data_owner>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "addresses_item = my_gis.content.search('destinations_address, owner:api_data_owner', 'feature layer')[0]\n",
    "addresses_item"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Address</th>\n",
       "      <th>ObjectId</th>\n",
       "      <th>SHAPE</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1151 W Lugonia Ave, Redlands, CA 92374</td>\n",
       "      <td>1</td>\n",
       "      <td>{\"x\": -13046371.7016, \"y\": 4037983.0551000014,...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1099 E Hospitality Ln, San Bernardino, CA 92408</td>\n",
       "      <td>2</td>\n",
       "      <td>{\"x\": -13053662.5736, \"y\": 4037947.9793, \"spat...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4756, 120 E State St, Redlands, CA 92373</td>\n",
       "      <td>3</td>\n",
       "      <td>{\"x\": -13044505.2086, \"y\": 4036358.3337000012,...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                           Address  ObjectId  \\\n",
       "0           1151 W Lugonia Ave, Redlands, CA 92374         1   \n",
       "1  1099 E Hospitality Ln, San Bernardino, CA 92408         2   \n",
       "2         4756, 120 E State St, Redlands, CA 92373         3   \n",
       "\n",
       "                                               SHAPE  \n",
       "0  {\"x\": -13046371.7016, \"y\": 4037983.0551000014,...  \n",
       "1  {\"x\": -13053662.5736, \"y\": 4037947.9793, \"spat...  \n",
       "2  {\"x\": -13044505.2086, \"y\": 4036358.3337000012,...  "
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "destinations_sdf = addresses_item.layers[0].query(as_df=True)\n",
    "destinations_sdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<FeatureSet> 3 features"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "destinations_fset = destinations_sdf.spatial.to_featureset()\n",
    "destinations_fset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With these inputs, solve the problem with Origin Destintion matrix solver. Look up [the doc](https://developers.arcgis.com/rest/network/api-reference/origin-destination-cost-matrix-service.htm) to understand how this tool works and its parameters. Remember, `0.0005` credits per input origin and destination pair will be charged. For example, if there are `100` origins and `200` destinations, the cost will be `10` credits. If you specify a cutoff or limit the number of destinations, for instance, to find only `5` closest destinations within `10` minutes of every origin, the cost will still be `10` credits, as the credits depend on the number of input origin destination pairs. \n",
    "\n",
    "`TargetDestinationCount`- The maximum number of destinations that must be found for the origin. If a value is not specified, the value from the Number of Destinations to Find parameter is used. \n",
    "\n",
    "`Cutoff`- Specify the travel time or travel distance value at which to stop searching for destinations from the origin. Any destination beyond the cutoff value will not be considered. The value needs to be in the units specified by the Time Units parameter if the impedance attribute in your travel mode is time based or in the units specified by the Distance Units parameter if the impedance attribute in your travel mode is distance based. If a value is not specified, the tool will not enforce any travel time or travel distance limit when searching for destinations.\n",
    "\n",
    "Specify `origin_destination_line_shape` to see the output in map. Even though the lines are straight for performance reasons, they always store the travel time and travel distance along the street network, not straight-line distance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Analysis succeeded? True\n",
      "CPU times: total: 531 ms\n",
      "Wall time: 7.94 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "# solve OD cost matrix tool for the origns and destinations\n",
    "from arcgis.network.analysis import generate_origin_destination_cost_matrix\n",
    "results = generate_origin_destination_cost_matrix(origins= origin_fset, #origins_fc_latlong, \n",
    "                                                destinations= destinations_fset, #destinations_fs_address,\n",
    "                                                cutoff=200,\n",
    "                                                origin_destination_line_shape='Straight Line')\n",
    "print('Analysis succeeded? {}'.format(results.solve_succeeded))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see the output lines table. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ObjectID</th>\n",
       "      <th>DestinationRank</th>\n",
       "      <th>Total_Time</th>\n",
       "      <th>Total_Distance</th>\n",
       "      <th>OriginID</th>\n",
       "      <th>OriginOID</th>\n",
       "      <th>OriginName</th>\n",
       "      <th>DestinationID</th>\n",
       "      <th>DestinationOID</th>\n",
       "      <th>DestinationName</th>\n",
       "      <th>Shape_Length</th>\n",
       "      <th>SHAPE</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>26.530202</td>\n",
       "      <td>31.756525</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Location 1</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>Location 2</td>\n",
       "      <td>0.149126</td>\n",
       "      <td>{\"paths\": [[[-117.18780686899998, 33.939331448...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>27.420455</td>\n",
       "      <td>26.612461</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Location 1</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>Location 3</td>\n",
       "      <td>0.117135</td>\n",
       "      <td>{\"paths\": [[[-117.18780686899998, 33.939331448...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>28.288924</td>\n",
       "      <td>37.391254</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Location 1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Location 1</td>\n",
       "      <td>0.129383</td>\n",
       "      <td>{\"paths\": [[[-117.18780686899998, 33.939331448...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>9.575</td>\n",
       "      <td>8.693815</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>Location 2</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "      <td>Location 3</td>\n",
       "      <td>0.068541</td>\n",
       "      <td>{\"paths\": [[[-117.11750543499994, 34.029918198...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>2</td>\n",
       "      <td>10.289274</td>\n",
       "      <td>10.453888</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>Location 2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>Location 1</td>\n",
       "      <td>0.088792</td>\n",
       "      <td>{\"paths\": [[[-117.11750543499994, 34.029918198...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>3</td>\n",
       "      <td>14.694424</td>\n",
       "      <td>16.225859</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>Location 2</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "      <td>Location 2</td>\n",
       "      <td>0.150462</td>\n",
       "      <td>{\"paths\": [[[-117.11750543499994, 34.029918198...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   ObjectID  DestinationRank  Total_Time  Total_Distance  OriginID  OriginOID  \\\n",
       "0         1                1   26.530202       31.756525         1          1   \n",
       "1         2                2   27.420455       26.612461         1          1   \n",
       "2         3                3   28.288924       37.391254         1          1   \n",
       "3         4                1       9.575        8.693815         2          2   \n",
       "4         5                2   10.289274       10.453888         2          2   \n",
       "5         6                3   14.694424       16.225859         2          2   \n",
       "\n",
       "   OriginName  DestinationID  DestinationOID DestinationName  Shape_Length  \\\n",
       "0  Location 1              2               2      Location 2      0.149126   \n",
       "1  Location 1              3               3      Location 3      0.117135   \n",
       "2  Location 1              1               1      Location 1      0.129383   \n",
       "3  Location 2              3               3      Location 3      0.068541   \n",
       "4  Location 2              1               1      Location 1      0.088792   \n",
       "5  Location 2              2               2      Location 2      0.150462   \n",
       "\n",
       "                                               SHAPE  \n",
       "0  {\"paths\": [[[-117.18780686899998, 33.939331448...  \n",
       "1  {\"paths\": [[[-117.18780686899998, 33.939331448...  \n",
       "2  {\"paths\": [[[-117.18780686899998, 33.939331448...  \n",
       "3  {\"paths\": [[[-117.11750543499994, 34.029918198...  \n",
       "4  {\"paths\": [[[-117.11750543499994, 34.029918198...  \n",
       "5  {\"paths\": [[[-117.11750543499994, 34.029918198...  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "od_df = results.output_origin_destination_lines.sdf\n",
    "od_df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Convert to matrix format\n",
    "We need to change the format to get a matrix with rows as origins and columns as destinations, with impedance value as travel time or travel distance. We will use the `pivot_table` feature of Pandas to accomplish that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"3\" halign=\"left\">Total_Distance</th>\n",
       "      <th colspan=\"3\" halign=\"left\">Total_Time</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>DestinationOID</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>OriginOID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>37.391254</td>\n",
       "      <td>31.756525</td>\n",
       "      <td>26.612461</td>\n",
       "      <td>28.288924</td>\n",
       "      <td>26.530202</td>\n",
       "      <td>27.420455</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>10.453888</td>\n",
       "      <td>16.225859</td>\n",
       "      <td>8.693815</td>\n",
       "      <td>10.289274</td>\n",
       "      <td>14.694424</td>\n",
       "      <td>9.575</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Total_Distance                       Total_Time             \\\n",
       "DestinationOID              1          2          3          1          2   \n",
       "OriginOID                                                                   \n",
       "1                   37.391254  31.756525  26.612461  28.288924  26.530202   \n",
       "2                   10.453888  16.225859   8.693815  10.289274  14.694424   \n",
       "\n",
       "                           \n",
       "DestinationOID          3  \n",
       "OriginOID                  \n",
       "1               27.420455  \n",
       "2                   9.575  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# filter only the required columns\n",
    "od_df2 = od_df[['DestinationOID','OriginOID','Total_Distance','Total_Time']]\n",
    "\n",
    "# user pivot_table\n",
    "od_pivot = od_df2.pivot_table(index='OriginOID', columns='DestinationOID')\n",
    "od_pivot"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Write the pivot table to disk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "od_pivot.to_csv('data/OD_Matrix.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is how we can get OD cost matrix when we have csv files with origin and destinations location information. We could read this matrix and provide this as input to a heuristics or an open-source algorithm. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "od_map = my_gis.map('Loma Linda, CA')\n",
    "od_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Screenshot]()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from arcgis.map.symbols import SimpleMarkerSymbolEsriSMS\n",
    "dest_symbol = SimpleMarkerSymbolEsriSMS(style='esriSMSSquare', color=[255,115,0,255], size=10)\n",
    "orig_symbol = SimpleMarkerSymbolEsriSMS(style='esriSMSCircle', color=[76,115,0,255], size=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "od_map.content.draw(results.output_origin_destination_lines)\n",
    "od_map.content.draw(destinations_fset, symbol=dest_symbol)\n",
    "od_map.content.draw(origin_fset, symbol=orig_symbol)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "This sample demonstrated how you can constuct an OD cost matrix using the Python API. We stared by defining `2` origin and `3` destination points. We used the `generate_origin_destination_cost_matrix()` method under the `network` module to compute the OD cost matrix.\n",
    "\n",
    "### How can you use this?\n",
    "The OD cost matrix becomes an important analytical output for downstream routing and other network analysis problems. Imagine you run a pizza shop and receive orders for delivery in a central location. Based on the distance to these demand points, you need to decide which supply point (pizza shop) should service which demand point (customer address). You can solve problems such as these by computing the OD cost matrix."
   ]
  }
 ],
 "metadata": {
  "esriNotebookRuntime": {
   "notebookRuntimeName": "ArcGIS Notebook Python 3 Standard",
   "notebookRuntimeVersion": "4.0"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "**Table of Contents**",
   "title_sidebar": "Contents",
   "toc_cell": true,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
